home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 076-100 / disk_087 / yaiffr / iff.c next >
C/C++ Source or Header  |  1992-05-06  |  7KB  |  307 lines

  1. /*  :ts=8 bk=0
  2.  *
  3.  * iff.c:    A cheesy IFF ILBM reader.
  4.  *
  5.  * Leo L. Schwab            8705.11
  6.  */
  7.  
  8. #include <exec/types.h>
  9. #include <exec/memory.h>
  10. #include <graphics/view.h>
  11. #include <stdio.h>
  12. #include "myiff.h"
  13.  
  14.  
  15. static struct ViewPort    *viewport;        /*  Working viewport  */
  16.  
  17.  
  18.  
  19. /*
  20.  * Okay, here's how this works.  This routine assumes that the file
  21.  * descriptor points to just past the FORM type and size fields in the file.
  22.  * It returns a pointer to a ViewPort structure with all necessary
  23.  * substructures, suitable for MakeVPort()ing.  It assumes someone else will
  24.  * know how to deallocate all said structures and resources.  Fortunately,
  25.  * there's enough information in ViewPorts to be able to intelligently free
  26.  * anything they may use.
  27.  */
  28. struct ViewPort *
  29. readform (fd, formsize)
  30. FILE *fd;            /*  File descriptor  */
  31. long formsize;            /*  Size of this FORM  */
  32. {
  33.     struct BitMapHeader    bmhd;
  34.     struct ChunkHeader    ch;
  35.     long            subtype;
  36.     register int        i, n;
  37.     char            gotheader = 0, gotcmap = 0, gotcamg = 0;
  38.     void            *tmp;
  39.  
  40.     if (!getsubtype (fd, &subtype))
  41.         return (NULL);
  42.     formsize -= sizeof (subtype);
  43.  
  44.     if (subtype != ILBM) {
  45.         puts ("FORM not an ILBM, skipping...");
  46.         skipchunk (fd, formsize - sizeof (subtype));
  47.         return (NULL);
  48.     }
  49.  
  50.     if (!(viewport = AllocMem ((long) sizeof (*viewport), MEMF_CLEAR)))
  51.         ackphft ("ViewPort allocation failed.");
  52.     InitVPort (viewport);
  53.  
  54.     while (formsize > 0) {
  55.  
  56.         if (!getchunkheader (fd, &ch))
  57.             ackphft ("Malformed IFF FORM.");
  58.         formsize -= sizeof (ch);
  59.  
  60.         switch (ch.TYPE) {
  61.         case BMHD: {
  62.             register struct BitMap *bm;
  63.             register struct RasInfo *ri;
  64.  
  65.             fread (&bmhd, (int) ch.chunksize, 1, fd);
  66.  
  67.             if (!(bm = AllocMem ((long) sizeof (*bm),
  68.                          MEMF_CLEAR)))
  69.                 ackphft ("BitMap allocation failed.");
  70.             InitBitMap (bm,
  71.                     (long) bmhd.nplanes,
  72.                     (long) bmhd.w, (long) bmhd.h);
  73.  
  74.             if (!(ri = AllocMem ((long) sizeof (*ri),
  75.                          MEMF_CLEAR)))
  76.                 ackphft ("RasInfo allocation failed.");
  77.             ri -> BitMap = bm;
  78.             ri -> RxOffset = ri -> RyOffset = NULL;
  79.             ri -> Next = NULL;
  80.  
  81.             viewport -> DWidth = bmhd.w;
  82.             viewport -> DHeight = bmhd.h;
  83.             viewport -> RasInfo = ri;
  84.  
  85.             gotheader = 1;
  86.             break;
  87.         }
  88.  
  89.         case CMAP: {
  90.             register UBYTE *ctable;
  91.             register UWORD *cmap;
  92.  
  93.             if (!(ctable = AllocMem (ch.chunksize, NULL)))
  94.                 ackphft ("EA colortable alloc failed.");
  95.             fread (ctable, (int) ch.chunksize, 1, fd);
  96.  
  97.             if (!(cmap = AllocMem (ch.chunksize * 2 / 3, NULL)))
  98.                 ackphft ("Colormap alloc failed.");
  99.  
  100.             for (i = n = 0; n < ch.chunksize; i++, n+=3)
  101.                 cmap[i] = ((ctable[n]   >> 4) << 8) +
  102.                       ((ctable[n+1] >> 4) << 4) +
  103.                       ( ctable[n+2] >> 4);
  104.  
  105.             if ((1 << bmhd.nplanes) != i)
  106. puts ("Warning: Colormap not sized to nplanes, hope it's HAM.");
  107.             viewport -> ColorMap = GetColorMap ((long) i);
  108.             LoadRGB4 (viewport, cmap, (long) i);
  109.             FreeMem (cmap, ch.chunksize * 2 / 3);
  110.             FreeMem (ctable, ch.chunksize);
  111.  
  112.             gotcmap = 1;
  113.             break;
  114.         }
  115.  
  116.         case CAMG:
  117.             /*  Use subtype as a temporary buffer  */
  118.             fread (&subtype, (int) ch.chunksize, 1, fd);
  119.             viewport -> Modes = (UWORD) (subtype & 0xffff);
  120.  
  121.             gotcamg = 1;
  122.             break;
  123.  
  124.         case BODY:
  125.             if (!gotheader || !gotcmap)
  126.                 ackphft ("BODY before BMHD or CMAP.");
  127.  
  128.             loadbitmap (fd, viewport, &bmhd);
  129.             break;
  130.  
  131.         case CRNG:
  132.         case GRAB:
  133.         case DEST:
  134.         case SPRT:
  135.         case DPPV:    /*  Anyone know what this one is for?  */
  136.             skipchunk (fd, ch.chunksize);
  137.             break;
  138.  
  139.         default:
  140.             printf ("Unrecognized chunk: 0x%lx\n", ch.TYPE);
  141.             skipchunk (fd, ch.chunksize);
  142.         }
  143.  
  144.         formsize -= ch.chunksize;
  145.         if (ch.chunksize & 1) {        /*  Odd length chunk  */
  146.             formsize --;
  147.             fseek (fd, 1L, 1);
  148.         }
  149.     }
  150.  
  151.     /*  Post-processing in case of lack of CAMG chunk  */
  152.     if (!gotcamg) {
  153.         if (bmhd.w > 370)    /*  Arbitrary limit  */
  154.             viewport -> Modes |= HIRES;
  155.         if (bmhd.h > 256)
  156.             viewport -> Modes |= LACE;
  157.     }
  158.  
  159.     tmp = viewport;
  160.     viewport = NULL;
  161.     return (tmp);
  162. }
  163.  
  164. loadbitmap (fd, vp, header)
  165. FILE *fd;
  166. struct ViewPort *vp;
  167. struct BitMapHeader *header;
  168. {
  169.     register struct BitMap    *bm;
  170.     register int        i, n;
  171.     int            plane_offset = 0;
  172.  
  173.     bm = vp -> RasInfo -> BitMap;
  174.  
  175.     if (header->Compression != cmpNone &&
  176.         header->Compression != cmpByteRun1)
  177.         ackphft ("Unrecognized compression technique.");
  178.  
  179.     for (i=0; i < bm->Depth; i++)
  180.         if (!(bm -> Planes[i] = AllocRaster ((long) vp -> DWidth,
  181.                              (long) vp -> DHeight)))
  182.             ackphft ("Bitplane allocation failed.");
  183.  
  184.     for (i=0; i < bm->Rows; i++) {
  185.         for (n=0; n < bm->Depth; n++) {
  186. /*- - - - - - - - - - -*/
  187. if (!header->Compression) {    /* No compression */
  188.     if (!fread (bm -> Planes[n] + plane_offset,
  189.             bm -> BytesPerRow, 1, fd))
  190.         ackphft ("Failure in BODY read.");
  191.  
  192. } else {
  193.     int        so_far;
  194.     register UBYTE    *dest = bm -> Planes[n] + plane_offset;
  195.     char        len;
  196.  
  197.     /*
  198.      * Note:  All file I/O after this point is assumed to be sucessful.
  199.      * This is clearly a poor assumption, but it saves on typing.
  200.      * And besides, putting the checking in is simple :-) :-).
  201.      */
  202.     so_far = bm -> BytesPerRow;
  203.     while (so_far > 0) {
  204.         if ((len = getc (fd)) >= 0) {    /*  Literal byte copy  */
  205.             so_far -= ++len;
  206.             fread (dest, len, 1, fd);
  207.             dest += len;
  208.  
  209.         } else if ((UBYTE) len == 128)    /*  NOP  */
  210.             ;
  211.  
  212.         else if (len < 0) {        /*  Replication count  */
  213.             UBYTE    byte;
  214.  
  215.             len = -len + 1;
  216.             so_far -= len;
  217.             byte = getc (fd);
  218.             while (--len >= 0)
  219.                 *dest++ = byte;
  220.         }
  221.     }
  222.     if (so_far)
  223.         ackphft ("Compression quite screwed up.");
  224. }
  225. /*- - - - - - - - - - -*/
  226.         }
  227.         plane_offset += bm -> BytesPerRow;
  228.     }
  229. }
  230.  
  231.  
  232. getchunkheader (fd, header)
  233. FILE *fd;        /*  File descriptor (that's what 'fd' stands for)  */
  234. struct ChunkHeader *header;
  235. {
  236.     return (fread (header, sizeof (*header), 1, fd));
  237. }
  238.  
  239. getsubtype (fd, type)
  240. FILE *fd;
  241. long *type;
  242. {
  243.     /*  !! NOT PORTABLE !!  */
  244.     return (fread (type, sizeof (*type), 1, fd));
  245. }
  246.  
  247. skipchunk (fd, size)
  248. FILE *fd;
  249. long size;
  250. {
  251.     fseek (fd, size, 1);
  252. }
  253.  
  254. /*
  255.  * This function assumes the existence of the global variable viewport, which
  256.  * is a pointer to a working ViewPort structure.  This is to allow graceful
  257.  * cleanup of allocated resources in case of an exceptional failure.
  258.  */
  259. freepict ()
  260. {
  261.     register struct BitMap *bm;
  262.     register int i;
  263.  
  264.     if (viewport) {
  265.         if (viewport -> RasInfo) {
  266.  
  267. /*- - - - - - - - - - -*/
  268. if (bm = viewport -> RasInfo -> BitMap) {
  269.     for (i=0; i < bm->Depth; i++)
  270.         if (bm -> Planes[i])
  271.             FreeRaster (bm -> Planes[i],
  272.                     (long) viewport -> DWidth,
  273.                     (long) viewport -> DHeight);
  274.     FreeMem (bm, (long) sizeof (*bm));
  275. }
  276. /*- - - - - - - - - - -*/
  277.  
  278.             FreeMem (viewport -> RasInfo,
  279.                  (long) sizeof (struct RasInfo));
  280.         }
  281.  
  282.         if (viewport -> ColorMap)
  283.             FreeColorMap (viewport -> ColorMap);
  284.  
  285.         FreeVPortCopLists (viewport);
  286.         FreeMem (viewport, (long) sizeof (*viewport));
  287.         viewport = NULL;
  288.     }
  289. }
  290.  
  291. closeviewport (vp)
  292. struct ViewPort *vp;
  293. {
  294.     viewport = vp;
  295.     freepict ();
  296. }
  297.  
  298. /*
  299.  * Premature termination routine.
  300.  */
  301. ackphft (str)
  302. char *str;
  303. {
  304.     freepict ();
  305.     die (str);
  306. }
  307.